//
//  JMLoadingView.m
//  JMLoadingView
//
//  Created by Matt Gallagher on 12/04/09.
//  Copyright Matt Gallagher 2009. All rights reserved.
// 
//  Permission is given to use this source code file, free of charge, in any
//  project, commercial or otherwise, entirely at your risk, with the condition
//  that any redistribution (in part or whole) of source code must retain
//  this copyright and permission notice. Attribution in compiled projects is
//  appreciated but not required.
//

#import "JMLoadingView.h"
#import <QuartzCore/QuartzCore.h>
#import "NSString+TextHeight.h"

CGPathRef NewPathWithRoundRect(CGRect rect, CGFloat cornerRadius);

@implementation JMLoadingView

@synthesize allowBackground;
@synthesize activityIndicatorView;
@synthesize superView;
@synthesize textLabel;
@synthesize loadingText;
@synthesize loadFlag;
@synthesize failText;
@synthesize successfulText;
@synthesize imageView;

/* 
 * loadingViewInView:
 *
 * Constructor for this view. Creates and adds a loading view for covering the
 * provided aSuperview.
 *
 * Parameters:
 *    aSuperview - the superview that will be covered by the loading view
 *
 * returns the constructed view, already added as a subview of the aSuperview
 *	(and hence retained by the superview)
 */

+ (id)loadingViewInView:(UIView *)superview_
			   WithText:(NSString *) text 
{
	return [[self class] loadingViewInView:superview_
								  WithText:text
								FailedText:nil
							  FinishedText:nil];
}

+ (id)loadingViewInView:(UIView *)superview_
			   WithText:(NSString *) loadingText_
			 FailedText:(NSString *) failText_
		   FinishedText:(NSString *) successfulText_
{
	JMLoadingView * loadingView = [[JMLoadingView alloc] initWithFrame:superview_.bounds 
														   LoadingText:loadingText_ 
															  FailText:failText_ 
														SuccessfulText:successfulText_ 
													   AllowBackground:YES];
	[superview_ addSubview:loadingView];
	
	loadingView.superView = superview_;
	return [loadingView autorelease];
}


- (void)dealloc
{
	[superView release];
	[textLabel release];
	[activityIndicatorView release];
	[loadingText release];
	[successfulText release];
	[failText release];
    [super dealloc];
}

- (id) initWithFrame:(CGRect) frame_ 
		 LoadingText:(NSString*) loadingText_ 
			FailText:(NSString*) failText_ 
	  SuccessfulText:(NSString*) successfulText_ 
	 AllowBackground:(BOOL) allowBackground_
{
	self = [super initWithFrame:frame_];
	if (self != nil) {
		self.loadingText = loadingText_;
		self.failText = failText_;
		self.successfulText = successfulText_;
		self.allowBackground = allowBackground_;
		
		textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
		if([loadingText_ length] > 0)
			textLabel.text = loadingText_;
		//else
//			textLabel.text = @"Loading";
		activityIndicatorView = [[UIActivityIndicatorView alloc]
								 initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

		loadFlag = JMLoadingViewLoading;
	}
	return self;
}


- (void) reload
{
	[self addSubview:activityIndicatorView];
	[self.imageView removeFromSuperview];
	self.loadFlag = JMLoadingViewLoading;
	[self setNeedsLayout];	
	[self setNeedsDisplay];	
}

- (void) finishLoading
{
	if([self.successfulText length] > 0)
		[self finishLoadingWithText:self.successfulText];
	else
		[self finishLoadingWithText:self.loadingText];
}

- (void)finishLoadingWithText:(NSString*) text
{	
	//Add checkmark view
	self.imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"loaded.png"]] autorelease];
	imageView.center = self.activityIndicatorView.center;
	[self.activityIndicatorView stopAnimating];
	[self.activityIndicatorView removeFromSuperview];	
	[self addSubview:imageView];
	loadFlag = JMLoadingViewSuccessful;	
	
	self.textLabel.text = text;
	[self setNeedsLayout];	
	[self setNeedsDisplay];
}

- (void) failLoading
{
	if([self.failText length] > 0)
		[self failLoadingWithText:self.failText];
	else
		[self failLoadingWithText:self.loadingText];
}

- (void)failLoadingWithText:(NSString*) text
{
	//Add checkmark view
	self.imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"notloaded.png"]] autorelease];
	
	imageView.center = self.activityIndicatorView.center;
	[self.activityIndicatorView stopAnimating];
	[self.activityIndicatorView removeFromSuperview];	
	[self addSubview:imageView];
	loadFlag = JMLoadingViewFailed;	
	
	self.textLabel.text = text;
	[self setNeedsLayout];	
	[self setNeedsDisplay];	
}

- (void) layoutSubviews
{
	[super layoutSubviews];
	
	self.opaque = NO;
	self.autoresizingMask =	UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	
	//Detect container view size
	CGFloat selfWidth = self.bounds.size.width;
	CGFloat labelHeight = [textLabel.text textHeightForSystemFontOfSize:GUI_FONT_SIZE_SMALL AndWidth:selfWidth - selfWidth*LOADING_RECT_TEXT_PADDING_PERCENT*2];
	//CGFloat labelHeight = ;
	//added by chen, to remove textLabel when there is no text.
	if (!textLabel.text) {
		labelHeight = 0;
	}
	
	CGRect labelFrame = CGRectMake(0, 
								   0,  
								   selfWidth - selfWidth*LOADING_RECT_TEXT_PADDING_PERCENT*2,
								   labelHeight);
	
	textLabel.frame = labelFrame;
	textLabel.lineBreakMode = UILineBreakModeWordWrap;
	textLabel.numberOfLines = 0;
	textLabel.textColor = [UIColor whiteColor];
	textLabel.backgroundColor = [UIColor clearColor];
	textLabel.textAlignment = UITextAlignmentCenter;
	textLabel.font = [UIFont boldSystemFontOfSize:GUI_FONT_SIZE_SMALL];
	textLabel.autoresizingMask = 
			UIViewAutoresizingFlexibleLeftMargin | 
			UIViewAutoresizingFlexibleRightMargin |
			UIViewAutoresizingFlexibleTopMargin |
			UIViewAutoresizingFlexibleBottomMargin;
	
	// Adjust Positions
	CGFloat totalHeight = textLabel.frame.size.height + activityIndicatorView.frame.size.height;
	labelFrame.origin.x = floor(0.5 * (self.bounds.size.width - labelFrame.size.width));
	labelFrame.origin.y = floor(0.5 * (self.bounds.size.height - totalHeight));
	textLabel.frame = labelFrame;	
	
	if(self.loadFlag == JMLoadingViewLoading)
	{
		activityIndicatorView.autoresizingMask =
				UIViewAutoresizingFlexibleLeftMargin |
				UIViewAutoresizingFlexibleRightMargin |
				UIViewAutoresizingFlexibleTopMargin |
				UIViewAutoresizingFlexibleBottomMargin;
		activityIndicatorView.hidesWhenStopped = YES;
		[activityIndicatorView startAnimating];
	
		CGRect activityIndicatorRect = activityIndicatorView.frame;
		activityIndicatorRect.origin.x = 0.5 * (self.bounds.size.width - activityIndicatorRect.size.width);
		activityIndicatorRect.origin.y = textLabel.frame.origin.y + textLabel.frame.size.height + LOADING_RECT_PADDING/2;
		activityIndicatorView.frame = activityIndicatorRect;
	
		// Set up the fade-in animation
		CATransition *animation = [CATransition animation];
		[animation setType:kCATransitionFade];
		[[self layer] addAnimation:animation forKey:@"layerAnimation"];	
		[self addSubview:activityIndicatorView];
	}
	
	[self addSubview:textLabel];
	
}

- (void)removeView
{
	[super removeFromSuperview];

	// Set up the animation
	CATransition *animation = [CATransition animation];
	[animation setType:kCATransitionFade];
	
	[[self layer] addAnimation:animation forKey:@"layerAnimation"];
}

- (void)drawRect:(CGRect)rect
{
	if(!allowBackground)
		return;
	
	rect.size.height -= 1;
	rect.size.width -= 1;
	
	rect = CGRectInset(rect, LOADING_RECT_PADDING_PERCENT * rect.size.width, LOADING_RECT_PADDING_PERCENT * rect.size.height);

	CGPathRef roundRectPath = NewPathWithRoundRect(rect, LOADING_ROUND_RECT_CORNER_RADIUS);
	
	CGContextRef context = UIGraphicsGetCurrentContext();

	CGContextSetRGBFillColor(context, 0, 0, 0, LOADING_BACKGROUND_OPACITY);
	CGContextAddPath(context, roundRectPath);
	CGContextFillPath(context);

	CGContextSetRGBStrokeColor(context, 1, 1, 1, LOADING_STROKE_OPACITY);
	CGContextAddPath(context, roundRectPath);
	CGContextStrokePath(context);
	
	CGPathRelease(roundRectPath);
}



// NewPathWithRoundRect
// Creates a CGPathRect with a round rect of the given radius.
CGPathRef NewPathWithRoundRect(CGRect rect, CGFloat cornerRadius)
{
	// Create the boundary path
	CGMutablePathRef path = CGPathCreateMutable();
	CGPathMoveToPoint(path, NULL,
					  rect.origin.x,
					  rect.origin.y + rect.size.height - cornerRadius);
	
	// Top left corner
	CGPathAddArcToPoint(path, NULL,
						rect.origin.x,
						rect.origin.y,
						rect.origin.x + rect.size.width,
						rect.origin.y,
						cornerRadius);
	
	// Top right corner
	CGPathAddArcToPoint(path, NULL,
						rect.origin.x + rect.size.width,
						rect.origin.y,
						rect.origin.x + rect.size.width,
						rect.origin.y + rect.size.height,
						cornerRadius);
	
	// Bottom right corner
	CGPathAddArcToPoint(path, NULL,
						rect.origin.x + rect.size.width,
						rect.origin.y + rect.size.height,
						rect.origin.x,
						rect.origin.y + rect.size.height,
						cornerRadius);
	
	// Bottom left corner
	CGPathAddArcToPoint(path, NULL,
						rect.origin.x,
						rect.origin.y + rect.size.height,
						rect.origin.x,
						rect.origin.y,
						cornerRadius);
	
	// Close the path at the rounded rect
	CGPathCloseSubpath(path);
	
	return path;
}

@end
